package com.songtech.login.util;

import com.alibaba.druid.util.PatternMatcher;
import com.alibaba.druid.util.ServletPathMatcher;
import com.songtech.base.listener.SysSessionContext;
import com.songtech.base.redis.RedisUtil;
import com.songtech.login.model.SysPosUser;
import com.songtech.login.service.PLoginService;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class WeChatFilter implements Filter {
    private Logger logger = Logger.getLogger(WeChatFilter.class);
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private PLoginService pLoginService;

    protected PatternMatcher pathMatcher = new ServletPathMatcher();
    private Set<String> exclusiveUrl;
    private static String appsecret;
    private static String appid;
    private static String indexUrl;
    private static String wechatToken;

    @Override
    public void init(FilterConfig filterConfig){
        appid = AuthUtil.appid;
        appsecret = AuthUtil.appsecret;
        indexUrl = AuthUtil.indexUrl;
        String exclusions = filterConfig.getInitParameter("exclusions");
        if (exclusions != null && exclusions.trim().length() != 0) {
            exclusiveUrl = new HashSet<String>(Arrays.asList(exclusions.split("\\s*,\\s*")));
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpSession session = httpRequest.getSession();
        String code = httpRequest.getParameter("code");
        String url = httpRequest.getRequestURI();
        logger.info("请求的地址:" + indexUrl + url);
        if (this.isExclusion(url)) {
            filterChain.doFilter(httpRequest, httpResponse);
            return;
        }
        SysPosUser userLogin = (SysPosUser) session.getAttribute("loginUser");//获取登录用户信息
        String loginOpenId = (String) session.getAttribute("openId");//获取openId

        //其他页面的ajax post请求进行判断
        if("POST".equals(httpRequest.getMethod()) && !"/plogin".equals(url)){
            if(userLogin ==null || loginOpenId == null){
                //session丢失
                httpResponse.setContentType("text/html;charset=utf-8");//设置返回数据格式html，不执行回调函数
                httpResponse.setHeader("sessionstatus", "timeout");// 在响应头设置session状态
                return;
            }else{
                SysPosUser userData = pLoginService.getUserByOpeniD(loginOpenId);//获取数据库的用户信息
                if(userData == null) {
                    //账号异地登录
                    session.removeAttribute("loginUser");
                    session.removeAttribute("openId");
                    httpResponse.setContentType("text/html;charset=utf-8");//设置返回数据格式html，不执行回调函数
                    httpResponse.setHeader("sessionstatus", "repeatlogin");// 在响应头设置session状态
                    return;
                }else{
                    filterChain.doFilter(httpRequest, httpResponse);
                    return;
                }
            }
        }

        //调用微信接口
        if (StringUtils.isEmpty(loginOpenId) && StringUtils.isEmpty(code)) {
            logger.info("第一步");
            StringBuilder sb = new StringBuilder();
            sb.append("https://open.weixin.qq.com/connect/oauth2/authorize?appid=");
            sb.append(appid);
            sb.append("&redirect_uri=");
            sb.append(indexUrl + url);
            sb.append("&response_type=code&scope=snsapi_base&state=STATE");
            sb.append("#wechat_redirect");
            logger.info("重定向的地址"+sb.toString());
            httpResponse.sendRedirect(sb.toString());
            return;
        }
        if (!StringUtils.isEmpty(code) && StringUtils.isEmpty(loginOpenId)) {
            logger.info("第二步");
            loginOpenId = getToken(code);
            session.setAttribute("openId",loginOpenId);
        }

        logger.info("登录的用户信息:"+userLogin);
        SysPosUser userData = null;
        if(StringUtils.isNotBlank(loginOpenId)) {
            userData = pLoginService.getUserByOpeniD(loginOpenId);//获取数据库的用户信息
        }
        logger.info("数据库的用户信息"+userData);

        if (userLogin==null || StringUtils.isEmpty(userLogin.getImei())) {
            //是否需要重新登录
            if(userData == null && !"/plogin".equals(url)) {
                //点击其他页面跳转到登录页面(session过期)
                httpResponse.sendRedirect("/wechatLogin.html?referer=" + url);
                return;
            }else if("/wechaTest.html".equals(url)){
                //注销登录(session失效)
                httpResponse.sendRedirect("/wechatLogin.html?referer="+url);
                return;
            }else if(userLogin == null && userData != null){
                //数据库有数据，session失效无用户信息
                session.setAttribute("loginUser",userData);
            }
        }else{
            if(userData == null && !"/plogin".equals(url)) {
                session.removeAttribute("loginUser");
                session.removeAttribute("openId");
                httpResponse.setContentType("text/html;charset=utf-8");
                PrintWriter out = httpResponse.getWriter();
                StringBuilder builder = new StringBuilder();
                builder.append("<script type=\"text/javascript\" charset=\"UTF-8\">");
                builder.append("alert(\"您的帐号已在其他机器登录，请重新登录\");");
                builder.append("window.top.location.href='/wechaTest.html';");
                builder.append("</script>");
                logger.info("提示信息:"+builder.toString());
                out.print(builder.toString());
                out.close();
                return;
            }
        }
        filterChain.doFilter(httpRequest, httpResponse);
    }

    @Override
    public void destroy() {

    }

    /**
     * 获取请求用户信息的access_token
     * @param code
     */
    private String getToken(String code){
        StringBuilder sb = new StringBuilder();
        String openId = null;
        sb.append("https://api.weixin.qq.com/sns/oauth2/access_token?appid=");
        sb.append(appid);
        sb.append("&secret=");
        sb.append(appsecret);
        sb.append("&code=");
        sb.append(code);
        sb.append("&grant_type=authorization_code");
        try {
            JSONObject jsonObject = AuthUtil.doGetJson(sb);
            //wechatToken = jsonObject.getString("access_token");
            openId = jsonObject.getString("openid");
            logger.info("微信获取的openid:"+openId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return openId;
    }

    /**
     * 获取用户信息
     * @param wechatToken
     * @param openid
     * @return
     */
    private JSONObject getUserInfo(String wechatToken,String openid){
        logger.info("获取用户信息的参数:"+wechatToken+"\n"+openid);
        StringBuilder sb = new StringBuilder();
        JSONObject userinfo = null;
        sb.append("https://api.weixin.qq.com/sns/userinfo?access_token=");
        sb.append(wechatToken);
        sb.append("&openid=");
        sb.append(openid);
        sb.append("&lang=zh_CN");
        try {
            userinfo = AuthUtil.doGetJson(sb);
            logger.info("获取的用户信息:"+userinfo.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return userinfo;
    }

    private boolean isExclusion(String requestURI) {
        if (this.exclusiveUrl != null && requestURI != null) {
            if (this.exclusiveUrl != null) {
                if (!requestURI.startsWith("/")) {
                    requestURI = "/" + requestURI;
                }
            }
            Iterator var2 = this.exclusiveUrl.iterator();
            String pattern;
            do {
                if (!var2.hasNext()) {
                    return false;
                }
                pattern = (String) var2.next();
            } while (!this.pathMatcher.matches(pattern, requestURI));
            return true;
        } else {
            return false;
        }
    }
}
